﻿package list;

import common.Node;

/**
 * 给定两个单链表的头节点head1和head2，这两个链表可能相交，也可能不相交。
 * 
 * 实现一个函数，如果两个链表相交，请返回相交的第一个结点，如果不相交，返回null即可。
 * 
 * 要求：时间复杂度：O（M+N）,额外空间复杂度：0（1）
 * 
 * @author Administrator
 *
 */
public class 两个单链表相交问题 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

	/**
	 * 子问题1：如何判断一个链表是否有环，如果有，则返回第一个进入环的结点，如果没有则返回null<br/>
	 * 1.
	 * 设置一个满指针slow和一个快指针fast。刚开始时slow和fast都指向head.然后slow每次移动一步,fast每次移动两步<br/>
	 * 2. 如果链表无环，那么fast指针在移动过程中，一定会先到达终点，一旦fast到达终点，说明链表是无环的。<br/>
	 * 3. 如果链表有环，那么fast和slow指针一定会在环中的某个位置相遇，当fast和slow相遇时，fast指针重新回到head的位置
	 * slow指针不动，接下来，fast重头开始重新一次移动一步，然后继续遍历<br/>
	 * 4. fast和slow指针一定会再次相遇，并且在第一个入环的结点处相遇<br/>
	 */
	public static Node getLoopNoe(Node head) {
		if (head == null || head.next == null || head.next.next == null) {
			return null;
		}
		Node fast = head.next.next, slow = head.next;
		while (fast != slow) {
			if (fast.next == null || fast.next.next == null) {
				return null;
			}
			fast = fast.next.next;
			slow = slow.next;
		}

		fast = head;// fast减少自己的步长
		while (fast != slow) {
			fast = fast.next;
			slow = slow.next;
		}
		return slow;
	}

	/**
	 * 子问题2：如何判断两个无环链表是否相交（如果有一个链表有环，这两个链表是不会相交的），
	 * 如果相交则返回第一个相交的结点，如果不相交，则返回null.<br/>
	 * 详细的过程如下：<br/>
	 * 1. 链表1从头开始，走到最后一个结点，记下长度len1和最后一个结点end1;<br/>
	 * 2. 链表2从头开始，走到最后一个结点，记下长度len2和最后一个结点end2;<br/>
	 * 3. 如果end1!=end2,说明两个链表不相交，返回null即可;如果end1==end2,则说明两个链表相相交<br/>
	 * 4.
	 */
	public static Node noLoop(Node head1, Node head2) {
		if (head1 == null || head2 == null) {
			return null;
		}
		Node cur1 = head1;
		Node cur2 = head2;
		int n = 0;
		while (cur1.next != null) {
			n++;
			cur1 = cur1.next;
		}
		while (cur2.next != null) {
			n--;
			cur2 = cur2.next;
		}

		if (cur1 != cur2) {
			return null;
		}
		// 如果cur1==cur2，则说明相交
		cur1 = n > 0 ? head1 : head2;
		cur2 = cur1 == head1 ? head2 : head1;

		n = Math.abs(n);
		while (n != 0) {
			n--;
			cur1 = cur1.next;
		}
		while (cur1 != cur2) {
			cur1 = cur1.next;
			cur2 = cur2.next;
		}
		return cur1;

	}
}
